/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.global;

import java.util.Collection;

import org.zhiqim.kernel.Z;
import org.zhiqim.kernel.model.maps.HashMapSC;
import org.zhiqim.kernel.model.maps.MapSC;
import org.zhiqim.kernel.service.Service;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Classes;

/**
 * 全局别名管理器
 *
 * @version v8.0.1 @author zgzou 2022年2月12日 新建与整理
 */
public class Cls
{
    private final MapSC map = new HashMapSC();
    
    /**********************************************************************/
    //类简称设置和获取
    /**********************************************************************/
    
    /** 判断是否有短名的类 */
    public boolean has(String alias)
    {
        return map.containsKey(alias);
    }
    
    /** 设置短名类名称和类结构到全局变量中 */
    public void add(String alias, Class<?> cls)
    {
        map.put(alias, cls);
    }
    
    /** 移除短名 */
    public void remove(String alias)
    {
        map.remove(alias);
    }
    
    /** 通过别名，找到对应的有别名的类 */
    public Class<?> get(String alias)
    {
        return map.get(alias);
    }
    
    /** 获取全局别名类列表 */
    public Collection<Class<?>> list()
    {
        return map.values();
    }
    
    /** 获取全局别名类列表 */
    public MapSC map()
    {
        return map;
    }
    
    /** 清除全局别名列表 */
    public void clear()
    {
        map.clear();
    }
    
    /** 如果是别名则返回真类名，否则返回当前值 */
    public String className(String className)
    {
        Class<?> cls = map.get(className);
        return cls == null?className:cls.getName();
    }
    
    /** 通过类名获取类结构，支持别名，优先别名，再查结构 */
    public Class<?> forName(String className)
    {
        Class<?> cls = get(className);
        if (cls != null)
            return cls;
        
        return Classes.forName(className);
    }
    
    /** 通过类名获取类实例，支持别名，优先别名，再查结构 */
    public Object newInstance(String className)
    {
        Class<?> cls = get(className);
        if (cls != null)
            return Classes.newInstance(cls);
        
        return Classes.newInstance(className);
    }
    
    /**********************************************************************/
    //服务ClassLoader下操作
    /**********************************************************************/
    
    /** 服务下查找类结构 */
    public Class<?> forName(String className, String serviceId)
    {
        Service service = Z.serv().get(serviceId);
        Asserts.as(service != null?null:"服务["+serviceId+"]不存在");
        
        Class<?> cls = get(className);
        if (cls != null)
            return cls;
        
        ClassLoader currLoader = Thread.currentThread().getContextClassLoader();
        try
        {
            Thread.currentThread().setContextClassLoader(service.getClassLoader());
            return Classes.forName(className);
        }
        finally
        {
            Thread.currentThread().setContextClassLoader(currLoader);
        }
    }
    
    /** 服务下的调用类的静态无参数方法 */
    public Object invoke(String serviceId, String className, String methodName) throws Exception
    {
        return invoke(serviceId, className, methodName, null, null);
    }
    
    /** 服务下的调用类的方法 */
    public Object invoke(String serviceId, String className, String methodName, Object obj, Object[] args) throws Exception
    {
        Service service = Z.serv().get(serviceId);
        Asserts.as(service != null?null:"服务["+serviceId+"]不存在");
        
        Class<?> cls = get(className);
        ClassLoader currLoader = Thread.currentThread().getContextClassLoader();
        try
        {
            Thread.currentThread().setContextClassLoader(service.getClassLoader());
            if (cls == null)
                cls = Classes.forName(className);
            
            Asserts.as(cls != null?null:"类["+className+"]不存在或不在该服务下");
            return Classes.invoke(cls, methodName, obj, args);
        }
        finally
        {
            Thread.currentThread().setContextClassLoader(currLoader);
        }
    }
}
